package com.dc.toolkit.guava.collect;

import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.junit.Test;

import java.util.*;
import java.util.concurrent.CopyOnWriteArraySet;

/**
 * Description: Guava_Sets 测试类
 * @author: gdc
 * @date: 2021/5/17
 * @version 1.0
 */
public class SetsTest {

    /**
     * 测试       Sets.newHashSet()   创建 HashSet
     */
    @Test
    public void testNewHashSet(){
        Set<String> set1 = Sets.newHashSet();
        Set<Integer> set2 = Sets.newHashSet(1, 2, 3);
        Set<Integer> set3 = Sets.newHashSet(set2);

        // 创建时指定大小
        HashSet<Object> set4 = Sets.newHashSetWithExpectedSize(10);
    }

    /**
     * 测试       Sets.newLinkedHashSet()   创建 LinkedHashSet
     */
    @Test
    public void testNewLinkedHashSet(){
        Set<Integer> set1 = Sets.newLinkedHashSet();
        set1.add(1);
        set1.add(2);
        set1.add(3);

        Set<Integer> set2 = Sets.newLinkedHashSet(set1);

        // 创建时指定大小
        LinkedHashSet<Object> set3 = Sets.newLinkedHashSetWithExpectedSize(10);
    }

    /**
     * 测试       Sets.newTreeSet()   创建 TreeSet
     */
    @Test
    public void testNewTreeSet(){
        TreeSet<Comparable> treeSet1 = Sets.newTreeSet();
        TreeSet<Comparable> treeSet2 = Sets.newTreeSet(treeSet1);
    }

    /**
     * 测试       Sets.newEnumSet()   创建EnumSet
     * 构造一个新的可变的EnumSet实例，该实例包含按自然顺序排列的给定元素
     */
    @Test
    public void testNewEnumSet(){
        EnumSet<SetEnum> enumSet = Sets.newEnumSet(
                Lists.newArrayList(SetEnum.A, SetEnum.B, SetEnum.A, SetEnum.C),
                SetEnum.class);
        System.out.println(enumSet);
    }

    /**
     * 测试       Sets.newConcurrentHashSet() 创建 ConcurrentHashMap
     */
    @Test
    public void testNewConcurrentHashSet(){
        Set<String> concurrentHashSet1 = Sets.newConcurrentHashSet();
        Set<String> concurrentHashSet2 = Sets.newConcurrentHashSet(concurrentHashSet1);
    }

    /**
     * 测试       Sets.newCopyOnWriteArraySet() 创建 CopyOnWriteArraySet
     */
    @Test
    public void testNewCopyOnWriteArraySet(){
        CopyOnWriteArraySet<String> copyOnWriteArraySet1 = Sets.newCopyOnWriteArraySet();
        CopyOnWriteArraySet<String> copyOnWriteArraySet2 = Sets.newCopyOnWriteArraySet(copyOnWriteArraySet1);
    }

    // -----------------------------------------------------------------------------------

    /**
     * 测试       两个集合的并集、交集、差集、A集合中包含B集合不存在的数据
     *              返回的是不可修改的 SetView
     */
    @Test
    public void test(){
        Set<String> S1 = Sets.newHashSet("1", "2", "3");
        Set<String> S2 = Sets.newHashSet("2", "3", "4");
        System.out.println("s1 >> " + S1);
        System.out.println("s2 >> " + S2);
        System.out.println("------------------------------------------");

        /**
         * 返回在s1中存在，但不再s2中存在的 >> [1]
         */
        System.out.println("返回在s1中存在，但不再s2中存在的 >> " + Sets.difference(S1, S2));
        /**
         * 返回在s2中存在， 但不再s1中存在的 >> [4]
         */
        System.out.println("返回在s2中存在， 但不再s1中存在的 >> " + Sets.difference(S2, S1));


        /**
         * 返回两个集合互斥集合 差集 >> [1, 4]
         */
        System.out.println("返回两个集合互斥集合 差集 >> " + Sets.symmetricDifference(S1, S2));

        /**
         * 返回两个集合的交集 >> [2, 3]
         */
        System.out.println("返回两个集合的交集 >> " + Sets.intersection(S1, S2));

        /**
         * 返回两个集合的并集 >> [1, 2, 3, 4]
         */
        System.out.println("返回两个集合的并集 >> " + Sets.union(S1, S2));
    }

    /**
     * 测试       多个Set的笛卡尔积组合
     */
    @Test
    public void testCartesianProduct() {
        Set<List<Integer>> set = Sets.cartesianProduct(
                Sets.newHashSet(1, 2),
                Sets.newHashSet(2, 3, 4),
                Sets.newHashSet(5, 6));
        System.out.println("笛卡尔积组合 >> ");
        set.forEach(System.out::println);
    }

    /**
     * 测试       对给定Set集合按照指定个数，进行组合
     */
    @Test
    public void testCombinations() {
        HashSet<Integer> set = Sets.newHashSet(1, 2, 3, 4);
        Set<Set<Integer>> combinations = Sets.combinations(set, 2);
        System.out.println("Set集合按照指定个数，进行组合 >> ");
        combinations.forEach(System.out::println);
    }

    /**
     * 测试       Sets.complementOf()     反向获得其余枚举值
     */
    @Test
    public void testComplementOf(){
        EnumSet<SetEnum> setEnums = Sets.complementOf(Lists.newArrayList(SetEnum.A, SetEnum.C));
        System.out.println(setEnums);

        EnumSet<SetEnum> setEnums2 = Sets.complementOf(
                Lists.newArrayList(SetEnum.A),
                SetEnum.class);
        System.out.println(setEnums2);
    }
}

@AllArgsConstructor
@Getter
enum SetEnum {
    A("a"),
    B("b"),
    C("c");

    private String code;
}